package de.tuhh.simsearch.model.persistence.usermgmt.entities;

import java.io.Serializable;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.ManyToMany;

import de.tuhh.simsearch.constants.Constants;

/**
 * The preference entity class represents the preference table in the user management database. A preference has a
 * content type ({@link Constants}) and a name, which are primary keys to the table in the database. The preference
 * entity also contains a set of preference subscribers. These are the users those who subscribed to this preference.
 * 
 * 
 * @author SimSearch 1
 * 
 * @see UserEntity
 * @see Constants
 */

@Entity
@IdClass(PreferenceEntityId.class)
public class PreferenceEntity implements Serializable {

  private static final long serialVersionUID = 1L;

  @Id private Integer contentID;
  @Id private String name;

  @ManyToMany(mappedBy = "preferences", cascade = CascadeType.PERSIST) private Set<UserEntity> preferenceSubscriber = new HashSet<UserEntity>();

  protected PreferenceEntity() {

  }

  /**
   * The preference entity class constructor, sets the name and the content type
   * 
   * @param name
   */
  public PreferenceEntity(String name, Integer contentID) {

    setName(name);
    setContentID(contentID);

  }

  /**
   * Gets the unmodifiable set of preference subscribers
   * 
   * @return the set of preference subscribers
   */
  public Set<UserEntity> getPreferenceSubscriber() {

    return Collections.unmodifiableSet(preferenceSubscriber);
  }

  /**
   * Adds a user as preference subscriber to this preference entity
   * 
   * @param u
   *          the user entity to add
   */
  public void addPreferenceSubscriber(UserEntity u) {

    preferenceSubscriber.add(u);
    if (!(u.getPreferences().contains(this))) {

      u.addPreference(this);
    }

  }

  /**
   * Removes a user from the set of preference subscribers.
   * 
   * @param u
   *          the user entity of the user to remove
   */
  public void removePreferenceSubscriber(UserEntity u) {

    this.preferenceSubscriber.remove(u);
    if (u.getPreferences().contains(this)) {

      u.removePreference(this);
    }
  }

  protected void setPreferenceSubscriber(Set<UserEntity> preferenceSubscriber) {

    this.preferenceSubscriber = preferenceSubscriber;
  }

  /**
   * Gets the name of the preference
   * 
   * @return the name of the preference
   */
  public String getName() {

    return name;
  }

  /**
   * Gets the content id of the preference, which encodes the content type
   * 
   * @return the content id
   */
  public Integer getContentID() {

    return contentID;
  }

  /**
   * Sets the name of the preference
   * 
   * @param name
   *          the name to be set
   */
  public void setName(String name) {

    this.name = name;
  }

  /**
   * Sets the content id of the preference. See {@link Constants} for valid values.
   * 
   * @param contentID
   *          the content id to set
   */
  public void setContentID(Integer contentID) {

    this.contentID = contentID;
  }
}


class PreferenceEntityId implements Serializable {

  /**
   * 
   */
  private static final long serialVersionUID = 6365983296791500881L;
  private Integer contentID;
  private String name;

  public PreferenceEntityId() {

  }

  /**
   * 
   * @param name
   */
  public void setName(String name) { // hier z.B. content name = text oder picture

    this.name = name;
  }

  /**
   * 
   * @return
   */
  public String getName() {

    return name;
    // return id.getName(); 29 12 13
  }

  /**
   * @return the contentID
   */
  public Integer getContentID() {

    return contentID;
  }

  /**
   * @param contentID
   *          the contentID to set
   */
  public void setContentID(Integer contentID) {

    this.contentID = contentID;
  }

  @Override
  public int hashCode() {

    return (contentID.toString() + name).hashCode();
  }

  @Override
  public boolean equals(Object obj) {

    boolean retval = false;

    if (obj instanceof PreferenceEntityId) {

      PreferenceEntityId prefID = (PreferenceEntityId) obj;
      retval = (prefID.getContentID().equals(this.contentID) && prefID.getName().equals(this.name));
    }

    return retval;
  }
}
